//
//  String+Ex.swift
//  
//
//  Created by tank on 2021/9/29.
//

import Foundation
import CommonCrypto

/// Extend String with `ex` proxy.
extension String: ExtensionCompatible {}

public extension Extension where Base == String {
    /// String to Int?
    var int: Int? {
        return Int(base)
    }
    
    /// String to Float?
    var float: Float? {
        return Float(base)
    }
    
    /// String to Double?
    var double: Double? {
        return Double(base)
    }
    
    var isUrlEncoded: Bool {
        return base != base.ex.decodeURI()
    }
    
    
    var base64Encode: String? {
        guard let data = base.data(using: .utf8) else {
            return nil
        }
        
        return data.base64EncodedString()
    }
    
    var base64Decode: String? {
        guard let data = Data(base64Encoded: base) else {
            return nil
        }
        
        return String(data: data, encoding: .utf8)
    }
    
    var pathExtension: String {
        return (base as NSString).pathExtension
    }
    
    var md5: String {
        let digestLen = Int(CC_MD5_DIGEST_LENGTH)
        let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
        
        CC_MD5(base.cString(using: .utf8), CC_LONG(base.lengthOfBytes(using: .utf8)), result)
        
        var hash = String()
        for index in 0 ..< digestLen {
            hash = hash.appendingFormat("%02x", result[index])
        }
        
        result.deallocate()
        
        return hash
    }
    
    var secCertificate: SecCertificate? {
        var temp = base
        temp = temp.replacingOccurrences(of: "-----BEGIN CERTIFICATE-----", with: "")
        temp = temp.replacingOccurrences(of: "-----END CERTIFICATE-----", with: "")
        temp = temp.replacingOccurrences(of: "\n", with: "")
        
        guard let data = Data(base64Encoded: temp) else {
            return nil
        }
        
        return SecCertificateCreateWithData(nil, data as CFData)
    }
    
    /// URLEncode 编码
    ///
    /// - Returns: String?
    func encodeURIComponent() -> String? {
        var allowedQueryParamAndKey = NSCharacterSet.urlQueryAllowed
        allowedQueryParamAndKey.remove(charactersIn: ";/?:@&=+$, #")
        return base.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey)
    }
    
    func encodeURI() -> String? {
        var allowedQueryParamAndKey = NSCharacterSet.urlQueryAllowed
        allowedQueryParamAndKey.insert("#")
        return base.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey)
    }
    
    /// URL解码
    func decodeURIComponent() -> String? {
        return base.removingPercentEncoding
    }
    
    func decodeURI() -> String? {
        return base.removingPercentEncoding
    }
    
    func add(urlParameters: [String: String]) -> String {
        guard var urlComponents = URLComponents(string: base) ?? URLComponents(string: base.ex.encodeURI() ?? "") else {
            return base
        }
        
        var queryItems = urlComponents.queryItems ?? []
        
        let parameters = urlParameters.map { key, value in
            return URLQueryItem(name: key, value: value)
        }
        queryItems.append(contentsOf: parameters)
        
        urlComponents.queryItems = queryItems
        
        return urlComponents.url?.absoluteString ?? base
    }
}
